#ifndef __M_EXCHANGE_H__
#define __M_EXCHANGE_H__

/**
 * @file exchange.hpp
 * @brief 消息队列交换机管理模块
 * 
 * 本模块实现交换机的声明、删除、持久化存储及内存管理功能。
 * 包含三个核心组件：
 * 1. Exchange - 交换机数据结构
 * 2. ExchangeMapper - 数据库持久化管理
 * 3. ExchangeManager - 内存管理及线程安全操作
 */

#include "../common/logger.hpp"          // 日志模块
#include "../common/helper.hpp"          // 通用工具函数
#include "../common/msg.pb.h"            // Protobuf消息定义
#include <google/protobuf/map.h>         // Protobuf map容器
#include <iostream>                      // 标准输入输出
#include <unordered_map>                 // 哈希表容器
#include <mutex>                         // 互斥锁
#include <memory>                        // 智能指针

namespace bitmq 
{
    /**
     * @struct Exchange
     * @brief 交换机数据结构
     * 
     * 表示消息队列中的虚拟交换机实体，负责实现消息路由的核心逻辑。
     * 支持三种类型：DIRECT（直连）、FANOUT（广播）、TOPIC（主题）
     */
    struct Exchange 
    {
        using ptr = std::shared_ptr<Exchange>; // 智能指针别名

        // 交换机属性
        std::string name;                // 交换机唯一标识（ASCII字母开头，可包含数字和连字符）
        ExchangeType type;               // 交换机类型 @see ExchangeType
        bool durable;                    // 持久化标志（true时服务重启后自动恢复）
        bool auto_delete;                // 自动删除标志（true时当所有队列解绑后自动删除）
        google::protobuf::Map<std::string, std::string> args; // 扩展参数键值对

        /// @brief 默认构造函数（用于Protobuf反序列化）
        Exchange() = default;

        /**
         * @brief 参数化构造函数
         * @param ename 交换机名称（需符合命名规范）
         * @param etype 交换机类型 @see ExchangeType
         * @param edurable 持久化标志
         * @param eauto_delete 自动删除标志
         * @param eargs 扩展参数（支持alternate-exchange等特殊配置）
         */
        Exchange(const std::string &ename, 
                ExchangeType etype, 
                bool edurable,
                bool eauto_delete,
                const google::protobuf::Map<std::string, std::string> &eargs)
            : name(ename), type(etype), durable(edurable), 
              auto_delete(eauto_delete), args(eargs) {}

        /**
         * @brief 从字符串解析参数到args map
         * @param str_args 参数字符串格式：key1=val1&key2=val2...
         * @note 示例："alternate-exchange=backup&max-length=1000"
         */
        void setArgs(const std::string &str_args) 
        {
            std::vector<std::string> sub_args;
            StrHelper::split(str_args, "&", sub_args); // 分割参数对
            
            for (auto &str : sub_args) 
            {
                size_t pos = str.find("=");
                if(pos == std::string::npos) 
                {
                    // DLOG("忽略无效参数格式: {}", str);
                    continue;
                }
                
                std::string key = str.substr(0, pos);
                std::string val = str.substr(pos + 1);
                args[key] = val; // 插入键值对
            }
        }

        /**
         * @brief 将args map序列化为字符串
         * @return 格式化的参数字符串
         * @note 生成的字符串可直接存储到数据库
         */
        std::string getArgs() 
        {
            std::string result;
            for (auto it = args.begin(); it != args.end(); ++it) 
            {
                if(it != args.begin()) result += "&"; // 分隔符处理
                result += it->first + "=" + it->second;
            }
            return result;
        }
    };

    // 交换机集合类型：名称到交换机对象的哈希映射
    using ExchangeMap = std::unordered_map<std::string, Exchange::ptr>;

    /**
     * @class ExchangeMapper
     * @brief 交换机持久化管理器
     * 
     * 职责：
     * 1. 管理SQLite数据库表结构
     * 2. 实现交换机数据的持久化存储
     * 3. 服务启动时从数据库恢复数据
     */
    class ExchangeMapper 
    {
    public:
        /**
         * @brief 构造函数
         * @param dbfile 数据库文件路径（示例：/var/bitmq/exchange.db）
         * @throws 当数据库打开失败时终止程序
         */
        ExchangeMapper(const std::string &dbfile)
            : _sql_helper(dbfile) // 初始化SQLite工具类
        {
            std::string path = FileHelper::parentDirectory(dbfile);
            FileHelper::createDirectory(path);  // 确保数据库目录存在
            assert(_sql_helper.open());         // 打开数据库连接
            createTable();                      // 创建数据表
        }

        /// @brief 创建交换机表（如果不存在）
        void createTable() 
        {
            const char* CREATE_TABLE = 
                "create table if not exists exchange_table("
                "name varchar(32) primary key, "  // 名称最长32字符
                "type int, "                      // 存储ExchangeType枚举值
                "durable int, "                   // 0/1表示布尔值
                "auto_delete int, "               // 同上
                "args varchar(128));";            // 参数字符串最大128字符
            
            if (!_sql_helper.exec(CREATE_TABLE, nullptr, nullptr)) 
            {
                DLOG("创建交换机表失败！");
                abort(); // 数据库错误直接终止程序（生产环境应抛出异常）
            }
        }

        /// @brief 删除交换机表（测试环境清理用）
        void removeTable() 
        {
            const char* DROP_TABLE = "drop table if exists exchange_table;";
            if (!_sql_helper.exec(DROP_TABLE, nullptr, nullptr)) 
            {
                DLOG("删除交换机表失败！");
                abort();
            }
        }

        /**
         * @brief 插入新交换机记录
         * @param exp 交换机智能指针
         * @return 是否插入成功
         */
        bool insert(Exchange::ptr &exp) 
        {
            std::stringstream ss;
            ss << "insert into exchange_table values('"
               << exp->name << "', " << exp->type << ", "
               << exp->durable << ", " << exp->auto_delete << ", '"
               << exp->getArgs() << "');"; // 构造插入SQL
            
            return _sql_helper.exec(ss.str(), nullptr, nullptr);
        }

        /// @brief 根据名称删除交换机记录
        void remove(const std::string &name) 
        {
            std::stringstream ss;
            ss << "delete from exchange_table where name='" << name << "';";
            _sql_helper.exec(ss.str(), nullptr, nullptr);
        }

        // @brief 从数据库恢复所有持久化交换机
        ExchangeMap recovery() 
        {
            ExchangeMap exchanges;
            const char* sql = "select name, type, durable, auto_delete, args from exchange_table;";
            _sql_helper.exec(sql, selectCallback, &exchanges);
            return exchanges;
        }

    private:
        // @brief SQL查询回调（将结果集转换为Exchange对象）
        static int selectCallback(void* arg, int numcol, char** row, char** fields) 
        {
            ExchangeMap* map = static_cast<ExchangeMap*>(arg);
            
            auto exp = std::make_shared<Exchange>();
            exp->name = row[0]; 
            exp->type = static_cast<ExchangeType>(std::stoi(row[1]));
            exp->durable = static_cast<bool>(std::stoi(row[2]));
            exp->auto_delete = static_cast<bool>(std::stoi(row[3]));
            
            if (row[4] != nullptr) 
                exp->setArgs(row[4]); // 解析参数字符串
            
            map->emplace(exp->name, exp);
            return 0;
        }

    private:
        SqliteHelper _sql_helper; // SQLite数据库操作工具
    };


    /**
     * @class ExchangeManager
     * @brief 交换机内存管理器
     * 
     * 职责：
     * 1. 提供线程安全的交换机操作接口
     * 2. 管理内存中的交换机数据
     * 3. 与持久化层交互保证数据一致性
     * 
     * @note 所有公共方法均通过互斥锁保证线程安全
     */
    class ExchangeManager 
    {
    public:
        using ptr = std::shared_ptr<ExchangeManager>;
        
        /**
         * @brief 构造函数
         * @param dbfile 数据库路径
         * @note 服务启动时自动加载所有持久化交换机到内存
         */
        ExchangeManager(const std::string &dbfile)
            : _mapper(dbfile) 
        {
            _exchanges = _mapper.recovery(); // 加载持久化数据
        }

        /**
         * @brief 声明/创建交换机
         * @param name 交换机名称
         * @param type 类型 @see ExchangeType
         * @param durable 是否持久化
         * @param auto_delete 是否自动删除
         * @param args 扩展参数
         * @return 是否成功（已存在返回true，数据库写入失败返回false）
         * 
         * @par 典型流程：
         * 1. 检查内存是否存在同名交换机
         * 2. 持久化交换机写入数据库
         * 3. 加入内存哈希表
         */
        bool declareExchange(const std::string &name,
                            ExchangeType type,
                            bool durable,
                            bool auto_delete,
                            const google::protobuf::Map<std::string, std::string> &args) 
        {
            std::unique_lock<std::mutex> lock(_mutex); // RAII锁
            
            // 存在性检查
            if (_exchanges.find(name) != _exchanges.end()) 
            {
                // DLOG("交换机 {} 已存在，跳过创建", name);
                return true; 
            }
            
            auto exp = std::make_shared<Exchange>(name, type, durable, auto_delete, args);
            
            // 持久化处理
            if (durable && !_mapper.insert(exp)) 
            {
                // DLOG("持久化交换机 {} 数据库写入失败", name);
                return false; 
            }
            
            _exchanges.emplace(name, exp);
            // DLOG("已创建交换机 {} (type={})", name, type);
            return true;
        }

        /**
         * @brief 删除交换机
         * @param name 交换机名称
         * @note 如果是持久化交换机，会同步删除数据库记录
         */
        void deleteExchange(const std::string &name) 
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _exchanges.find(name);
            if (it == _exchanges.end())
            {
                // DLOG("尝试删除不存在的交换机: {}", name);
                return;
            }
            
            // 持久化处理
            if (it->second->durable) 
            {
                _mapper.remove(name);
                // DLOG("已删除持久化交换机: {}", name);
            }
            
            _exchanges.erase(it);
        }

        /// @brief 查询交换机
        Exchange::ptr selectExchange(const std::string &name) 
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _exchanges.find(name);
            return (it != _exchanges.end()) ? it->second : nullptr;
        }

        /// @brief 判断交换机是否存在
        bool exists(const std::string &name) 
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _exchanges.find(name) != _exchanges.end();
        }

        /// @brief 获取当前交换机数量
        size_t size() 
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _exchanges.size();
        }

        /**
         * @brief 清空所有数据（仅测试使用）
         * @warning 会删除数据库表，生产环境禁用！
         */
        void clear() 
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _mapper.removeTable(); 
            _exchanges.clear();    
            DLOG("已清空所有交换机数据");
        }

    private:
        std::mutex _mutex;         // 互斥锁（保障线程安全）
        ExchangeMapper _mapper;    // 持久化管理器实例
        ExchangeMap _exchanges;    // 内存中的交换机映射表（哈希表实现）
    };
}

#endif // __M_EXCHANGE_H__ 